import Vue from 'vue';
import { createDecorator } from 'vue-class-component';
// 以下代码逻辑未完善

export interface RepeatCallOption {
  afterLoadOutfield?: boolean;
  duration?: number;
  immediate?: boolean;
}

declare type LoadOutfieldStatus = 'cancel' | 'success' | 'fail';

const KEY_REPEAT_HOLDER = '__key_repeat_holder__';

export function repeatCall({
  afterLoadOutfield = true,
  duration = 60000,
  immediate = true,
}: RepeatCallOption = {}) {
  return createDecorator((componentOptions, k) => {
    const method = componentOptions.methods && componentOptions.methods[k];
    if (!method) {
      throw new TypeError('装饰的必须是方法');
    }
    const opts = componentOptions as any;
    if (!opts.methods) {
      opts.methods = {};
    }
    let holderGetter = opts.methods[KEY_REPEAT_HOLDER];
    if (!holderGetter) {
      holderGetter = (() => {
        const holder = {};
        return () => holder;
      })();
      opts.methods[KEY_REPEAT_HOLDER] = holderGetter;
    }
    const holder = holderGetter();
    let methodMap = holder[duration];
    if (!methodMap) {
      methodMap = {};
      holder[duration] = methodMap;
    }
    methodMap[k] = {
      duration,
      afterLoadOutfield,
      immediate,
      method,
    };
  });
}

const KEY_METHODS_INTERVALS = '__key__methods__intervals__';

function initMethodsTimeouts(target: any) {
  let intervals: any = target && target[KEY_METHODS_INTERVALS];
  if (intervals && intervals.length !== 0) {
    console.log('停止周期方法调用');
  }
  if (!intervals) {
    intervals = [];
    target[KEY_METHODS_INTERVALS] = intervals;
  }
  intervals.forEach((it: any) => {
    clearInterval(it);
  });
}

Vue.mixin({
  async mounted() {
    const self = this as any;
    const methods = self.$options.methods;
    const repeatHolderGetter = methods && methods[KEY_REPEAT_HOLDER];
    if (repeatHolderGetter) {
      console.log('initMethodsTimeouts', repeatHolderGetter);
      initMethodsTimeouts(this);
      const holder = repeatHolderGetter();
      const immediateItems: any[] = [];
      Object.entries(holder).forEach(([key, val]: any[]) => {
        Object.values(val).forEach((v: any) => {
          if (v.immediate) {
            immediateItems.push(v);
          }
        });
      });
      immediateItems.forEach((it: any) => {
        it.method.call(this);
      });

      Object.keys(holder).forEach((time: any) => {
        self[KEY_METHODS_INTERVALS].push(setInterval(() => {
          Object.values(holder[time]).forEach((it: any) => {
            it.method.call(self);
          });
        }, time));
      });
    }
  },
  beforeDestroy() {
    initMethodsTimeouts(this);
  },
});
